package com.zz.springboot.service.impl;

import com.zz.springboot.constant.TypeConstants;
import com.zz.springboot.dto.DataDTO;
import com.zz.springboot.dto.MaxMoneyParamDto;
import com.zz.springboot.manager.MaxMoneyParamManager;
import com.zz.springboot.resp.enums.RespCodeEnum;
import com.zz.springboot.exception.BizException;
import com.zz.springboot.manager.AoMenManager;
import com.zz.springboot.manager.XiangGangManager;
import com.zz.springboot.resp.vo.ClassifyStatisticsDetail;
import com.zz.springboot.resp.vo.ClassifyStatisticsInfo;
import com.zz.springboot.resp.vo.ProfitAnalysisInfo;
import com.zz.springboot.service.AnalyseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AnalyseServiceImpl implements AnalyseService {

    @Autowired
    private AoMenManager aoMenManager;

    @Autowired
    private XiangGangManager xiangGangManager;

    @Autowired
    private MaxMoneyParamManager maxMoneyParamManager;

    @Override
    public void dataStatistics(String category, List<DataDTO> dataDTOS, List<ClassifyStatisticsInfo> res, Integer type) {

        ClassifyStatisticsInfo info = new ClassifyStatisticsInfo();
        ClassifyStatisticsDetail detail = new ClassifyStatisticsDetail();

        double buy_sum = dataDTOS.stream().mapToDouble(u -> u.getBuyMoney()).sum();
        double eat_sum = dataDTOS.stream().mapToDouble(u -> u.getEatMoney()).sum();
        double exclude_sum = dataDTOS.stream().mapToDouble(u -> u.getExcludeMoney()).sum();

        log.info("【{}】：{}-数据有{}条,总买入{}元,消化{}元,报出{}元", type == 1 ? "澳门" : "香港", category, dataDTOS.size(), buy_sum, eat_sum, exclude_sum);

        info.setClassification(category);
        detail.setCount(dataDTOS.size());
        detail.setBuyTotal(buy_sum);
        detail.setEatTotal(eat_sum);
        detail.setExcludeTotal(exclude_sum);
        info.setDetail(detail);

        res.add(info);

    }

    @Override
    public List<ClassifyStatisticsInfo> oddsEvensAnalyse(Integer type) {
        List<ClassifyStatisticsInfo> res = new ArrayList<>();

        for (String category : TypeConstants.oddEvenConstant) {
            List<DataDTO> odds_data = new ArrayList<>();
            if (TypeConstants.AOMEN.equals(type)) {
                //以category为维度，获得表中的对应数据
                odds_data = aoMenManager.selectOddsOrEvensData(category);
            } else if (TypeConstants.XiangGang.equals(type)) {
                odds_data = xiangGangManager.selectOddsOrEvensData(category);
            } else {
                throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
            }
            //以category维度统计
            dataStatistics(category, odds_data, res, type);
        }

        return res;
    }

    @Override
    public List<ClassifyStatisticsInfo> bigLittleAnalyse(Integer type) {
        List<ClassifyStatisticsInfo> res = new ArrayList<>();

        for (String category : TypeConstants.bigLittleConstant) {
            List<DataDTO> odds_data = new ArrayList<>();
            if (TypeConstants.AOMEN.equals(type)) {
                //以category为维度，获得表中的对应数据
                odds_data = aoMenManager.selectBigLittle(category);
            } else if (TypeConstants.XiangGang.equals(type)) {
                odds_data = xiangGangManager.selectBigLittle(category);
            } else {
                throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
            }
            //以category维度统计
            dataStatistics(category, odds_data, res, type);
        }

        return res;
    }

    @Override
    public List<ClassifyStatisticsInfo> animalsAnalyse(Integer type) {
        List<ClassifyStatisticsInfo> res = new ArrayList<>();

        for (String category : TypeConstants.animalConstant) {
            List<DataDTO> odds_data = new ArrayList<>();
            if (TypeConstants.AOMEN.equals(type)) {
                //以category为维度，获得表中的对应数据
                odds_data = aoMenManager.selectAnimalsData(category);
            } else if (TypeConstants.XiangGang.equals(type)) {
                odds_data = xiangGangManager.selectAnimalsData(category);
            } else {
                throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
            }
            //以category维度统计
            dataStatistics(category, odds_data, res, type);
        }

        return res;
    }

    @Override
    public List<ClassifyStatisticsInfo> colorsAnalyse(Integer type) {
        List<ClassifyStatisticsInfo> res = new ArrayList<>();

        for (String category : TypeConstants.colorConstant) {
            List<DataDTO> odds_data = new ArrayList<>();
            if (TypeConstants.AOMEN.equals(type)) {
                //以category为维度，获得表中的对应数据
                odds_data = aoMenManager.selectColorData(category);
            } else if (TypeConstants.XiangGang.equals(type)) {
                odds_data = xiangGangManager.selectColorData(category);
            } else {
                throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
            }
            //以category维度统计
            dataStatistics(category, odds_data, res, type);
        }

        return res;
    }

    @Override
    public List<ClassifyStatisticsInfo> tailsAnalyse(Integer type) {
        List<ClassifyStatisticsInfo> res = new ArrayList<>();

        for (String category : TypeConstants.digitConstant) {
            List<DataDTO> odds_data = new ArrayList<>();
            if (TypeConstants.AOMEN.equals(type)) {
                //以category为维度，获得表中的对应数据
                odds_data = aoMenManager.selectTailData(category);
            } else if (TypeConstants.XiangGang.equals(type)) {
                odds_data = xiangGangManager.selectTailData(category);
            } else {
                throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
            }
            //以category维度统计
            dataStatistics(category, odds_data, res, type);
        }

        return res;
    }

    @Override
    public ProfitAnalysisInfo profitAnalyse(Integer type) {
        ProfitAnalysisInfo info = new ProfitAnalysisInfo();
        // 设定金额
        String username = (String) SecurityUtils.getSubject().getSession().getAttribute("username");
        MaxMoneyParamDto maxMoneyParam = maxMoneyParamManager.getMaxMoneyParam(username);
        // 计算其它参数
        if (TypeConstants.AOMEN.equals(type)) {
            List<DataDTO> dataDTOS = aoMenManager.selectAllData();
            calculateProfitCondition(dataDTOS, info);
            info.setSetSingleMaxEatMoney(maxMoneyParam.getAomenMaxValue());
        } else if (TypeConstants.XiangGang.equals(type)) {
            List<DataDTO> dataDTOS = xiangGangManager.selectAllData();
            calculateProfitCondition(dataDTOS, info);
            info.setSetSingleMaxEatMoney(maxMoneyParam.getXianggangMaxValue());
        } else {
            log.error("参数错误！");
            throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
        }

        return info;
    }

    private void calculateProfitCondition(List<DataDTO> dataDTOS, ProfitAnalysisInfo info){
        // 总买入金额
        int totalBuyMoney = (int) dataDTOS.stream().mapToDouble(DataDTO::getBuyMoney).sum();
        // 总报出金额
        int totalExcludeMoney = (int) dataDTOS.stream().mapToDouble(DataDTO::getExcludeMoney).sum();
        // 总消化金额
        int totalEatMoney = (int) dataDTOS.stream().mapToDouble(DataDTO::getEatMoney).sum();
        // 实际单个号码最大消化金额
        int practicalSingleMaxEatMoney = (int) dataDTOS.stream().mapToDouble(DataDTO::getEatMoney).max().orElse(0);
        // 实际单个号码最小消化金额
        int practicalSingleMinEatMoney = (int) dataDTOS.stream().mapToDouble(DataDTO::getEatMoney).min().orElse(0);
        // 最大亏损
        int maxLoss = (int)(totalEatMoney - totalEatMoney * 0.07 - practicalSingleMaxEatMoney * 45);
        // 最大利润
        int maxEarn = (int)(totalEatMoney - totalEatMoney * 0.07 - practicalSingleMinEatMoney * 45);
        // 盈利的单个号码限制金额
        int earnLimitMoney =(int) Math.floor((totalEatMoney - totalEatMoney * 0.07) / 45);
        // 会亏钱的号码
        List<Integer> lossNums = dataDTOS.stream()
                .filter(u -> u.getEatMoney() > earnLimitMoney)
                .map(DataDTO::getNum)
                .collect(Collectors.toList());

        info.setBuyTotalMoney(totalBuyMoney);
        info.setExcludeTotalMoney(totalExcludeMoney);
        info.setEatTotalMoneys(totalEatMoney);
        info.setPracticalSingleMaxEatMoney(practicalSingleMaxEatMoney);
        info.setPracticalSingleMinEatMoney(practicalSingleMinEatMoney);
        info.setCurrentMaxLossMoney(maxLoss);
        info.setCurrentMaxEarnMoney(maxEarn);
        info.setEarnSingleLimitedEatMoney(earnLimitMoney);
        info.setLossNums(lossNums);
    }
}
